const fs = require('fs');
const path = require('path');
const { minify } = require('terser');
const axios = require('axios');
const archiver = require('archiver');
const sdk = require('@baiducloud/sdk');
const BosClient = sdk.BosClient;

// 设置输入和输出目录
const INPUT_DIR = path.join(__dirname, '..', 'main');
const OUTPUT_DIR = path.join(__dirname, 'dist');

// 指定不想压缩的文件或目录
const EXCLUDE_FILES = [
    'main.js',
    'preload.js',
    'minify.js',
    'deploy.js',
    'node_modules',
    'dist',
    'package-lock.json',
    path.join('ipcHandlers', 'remotes')
].map((exclude) =>
    path.resolve(INPUT_DIR, exclude)
);

// 指定想要拷贝的文件或目录
const INCLUDE_FILES = [path.join(__dirname, 'VERSION')];

// 检测路径是否应该被排除
function shouldExclude(filePath) {
    return EXCLUDE_FILES.some((excludedPath) => filePath === excludedPath || filePath.startsWith(`${excludedPath}${path.sep}`));
}

// 递归获取所有js和json文件
function getFiles(dir) {
    let jsFiles = [];
    let jsonFiles = [];
    const items = fs.readdirSync(dir);

    items.forEach((item) => {
        const fullPath = path.join(dir, item);
        if (shouldExclude(fullPath)) {
            return;
        }
        const stat = fs.statSync(fullPath);
        if (stat.isFile() && item.endsWith('.js')) {
            jsFiles.push(fullPath);
        } else if (stat.isFile() && item.endsWith('.json')) {
            jsonFiles.push(fullPath);
        } else if (stat.isDirectory()) {
            let files = getFiles(fullPath);
            jsFiles = jsFiles.concat(files.jsFiles);
            jsonFiles = jsonFiles.concat(files.jsonFiles);
        }
    });

    return { jsFiles, jsonFiles };
}

// 删除目录并创建空目录
function recreateOutputDir() {
    if (fs.existsSync(OUTPUT_DIR)) {
        deleteFolderRecursive(OUTPUT_DIR);
    }
    fs.mkdirSync(OUTPUT_DIR);
}

// 递归删除目录
function deleteFolderRecursive(path) {
    if (fs.existsSync(path)) {
        fs.readdirSync(path).forEach((file) => {
            const curPath = path + '/' + file;
            if (fs.lstatSync(curPath).isDirectory()) {
                deleteFolderRecursive(curPath);
            } else {
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
}

// 拷贝文件到输出目录
function copyFilesToOutput() {
    INCLUDE_FILES.forEach((fileOrDir) => {
        const relativePath = path.relative(INPUT_DIR, fileOrDir);
        const outputFilePath = path.join(OUTPUT_DIR, relativePath);
        // console.log(`from ${fileOrDir} to ${outputFilePath}`);

        if (fs.existsSync(fileOrDir)) {
            if (fs.statSync(fileOrDir).isDirectory()) {
                // 如果是目录，递归拷贝目录下的所有文件
                copyDirRecursive(fileOrDir, outputFilePath);
            } else {
                // 如果是文件，直接拷贝
                const outputDir = path.dirname(outputFilePath);
                if (!fs.existsSync(outputDir)) {
                    fs.mkdirSync(outputDir, { recursive: true });
                }
                fs.copyFileSync(fileOrDir, outputFilePath);
            }
        }
    });
}

// 递归拷贝目录下的所有文件
function copyDirRecursive(src, dest) {
    console.log(`copyDirRecursive from ${src} to ${dest}`);
    const entries = fs.readdirSync(src, { withFileTypes: true });

    fs.mkdirSync(dest, { recursive: true });

    entries.forEach((entry) => {
        const srcPath = path.join(src, entry.name);
        const destPath = path.join(dest, entry.name);

        entry.isDirectory() ? copyDirRecursive(srcPath, destPath) : fs.copyFileSync(srcPath, destPath);
    });
}

// 压缩对应的dist目录
async function zipDirectory(sourceDir, outPath) {
    const archive = archiver('zip', { zlib: { level: 9 } });
    const stream = fs.createWriteStream(outPath);

    return new Promise((resolve, reject) => {
        archive
            .directory(sourceDir, false)
            // .directory(sourceDir, path.basename(sourceDir))
            .on('error', (err) => reject(err))
            .pipe(stream);

        stream.on('close', () => resolve());
        archive.finalize();
    });
}

const config = {
    endpoint: 'http://bd.bcebos.com',
    credentials: {
        ak: '6356708ce8d342bf965f2047d7c3cdb2',
        sk: 'd4837f696fdf4cf4abf11a80a1067abb'
    }
};

// BOS相关操作
const bucket = 'label-anything';
const client = new BosClient(config);

async function getCurrentVersion(indexFilePath) {
    try {
        let index_url = 'https://label-anything.bd.bcebos.com/' + indexFilePath;
        let resp = await axios.get(index_url);
        return resp.data.trim();
    } catch (error) {
        // console.log(error);
        return null;
    }
}

function incrementVersion(version) {
    const parts = version.split('.').map(Number);
    parts[2] += 1;
    return parts.join('.');
}

async function uploadFileToBOS(localFilePath, remoteFileName) {
    try {
        const response = await client.putObjectFromFile(bucket, remoteFileName, localFilePath);
        // console.log(`${remoteFileName} uploaded successfully`);
        return response;
    } catch (error) {
        console.error(`Failed to upload ${remoteFileName}:`, error);
        throw error;
    }
}

async function main() {
    // 确保输出目录存在
    recreateOutputDir();

    // 拷贝白名单文件和目录到输出目录
    copyFilesToOutput();

    // 获取所有JS文件，并执行压缩和混淆操作
    let files = getFiles(INPUT_DIR);
    files.jsFiles.forEach(async (file) => {
        const fileContents = fs.readFileSync(file, 'utf-8');
        const result = await minify(fileContents);
        const outputFilePath = file.replace(INPUT_DIR, OUTPUT_DIR);
        const outputDir = path.dirname(outputFilePath);

        // 确保输出文件的目录存在
        if (!fs.existsSync(outputDir)) {
            fs.mkdirSync(outputDir, { recursive: true });
        }

        // 写入压缩和混淆后的内容到输出文件中
        fs.writeFileSync(outputFilePath, result.code, 'utf-8');
    });
    console.log('## Minify js Files OK!');

    // 拷贝所有的json文件到dist目录中
    files.jsonFiles.forEach(async (file) => {
        const relativePath = path.relative(INPUT_DIR, file);
        const outputFilePath = path.join(OUTPUT_DIR, relativePath);
        const outputDir = path.dirname(outputFilePath);

        // 确保输出文件的目录存在
        if (!fs.existsSync(outputDir)) {
            fs.mkdirSync(outputDir, { recursive: true });
        }
        fs.copyFileSync(file, outputFilePath);
    });
    console.log('## Copy json Files OK!');

    // 获取当前版本号
    const indexFilePath = '/labelapp/server/VERSION';
    let currentVersion = await getCurrentVersion(indexFilePath);
    console.log(`## Current version: ${currentVersion}`);
    if (currentVersion == null) {
        console.log('## Current version not found, please check network connection.');
        return;
    }

    // 增量版本号，并更新到dist输出目录下
    const newVersion = incrementVersion(currentVersion);
    const newVersionPath = path.join(OUTPUT_DIR, 'VERSION');
    console.log(`## New version: ${newVersion}`);
    fs.writeFileSync('VERSION', newVersion);
    fs.writeFileSync(newVersionPath, newVersion);

    // 压缩文件并使用新版本号命名
    const distDir = OUTPUT_DIR;
    const zipFilePath = `dist-${newVersion}.zip`;
    await zipDirectory(distDir, zipFilePath);
    console.log(`## Directory compressed to ${zipFilePath}`);

    // 上传压缩文件到百度云BOS
    let remotePath = `/labelapp/server/${zipFilePath}`;
    await uploadFileToBOS(zipFilePath, remotePath);
    console.log(`## File ${remotePath} uploaded to BOS.`);

    // 上传新的版本号到VERSION
    await uploadFileToBOS('VERSION', indexFilePath);
    console.log(`## Updated version info to BOS.`);

    // 清理临时压缩文件
    fs.unlinkSync(zipFilePath);
    // fs.unlinkSync('VERSION');
    console.log('## Temporary file cleaned up.');
}

main();
